/*
 * Copyright (c) 2017-2021, Lindenis Tech. Ltd.
 * All rights reserved.
 *
 * File:
 *
 * Description:
 *
 * Author:
 *      xiaoshujun@lindeni.com
 *
 * Create Date:
 *      2021/03/08
 *
 * History:
 *
 */

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>

#include "lindmix.h"
#include "adev_wrapper.h"

#include "osal_log.h"
#include "osal_common.h"

typedef struct _sample_adev_context_t
{
    _handle_t       h_ai;
    _handle_t       h_ao;
    adev_config_t   ai_config;
    adev_config_t   ao_config;
} sample_adev_context_t;

static int _ai_cb(void * user, void * data, int size)
{
    sample_adev_context_t * p_ctx = (sample_adev_context_t*)user;
    _handle_t h_ao = p_ctx->h_ao;
    dump_hex(data, 16, 16);
    adev_out_write(p_ctx->h_ao, data, size);
    return 0;
}

static void print_usage_adev(char * this)
{
    printf("\033[32m");
    printf("Usage: \n");
    printf("    %s <options>\n", this);
    printf("    options parameters: \n");
    printf("        -i [adev_in]    : audio input device id, 0: codec, 1: hdmi, default '0' \n");
    printf("        -o [adev_out]   : audio output device id, 0: codec, 1: hdmi, default '0' \n");
    printf("        -c [channels]   : audio capture/output channels, default '1' \n");
    printf("        -r [sample_rate]: audio capture/output sample rate, default '48000' \n");
    printf("        -t [time_s]     : test duration in seconds, default '5' \n");
    printf("    such as: %s \n", this);
    printf("         or: %s -i 0 -o 1 -c 2 -r 16000 \n", this);
    printf("\033[0m\n");
}

int main(int argc, char **argv)
{
    int ret = 0, i = 0;
    sample_adev_context_t context = {0};
    int channels = 1;
    int sample_rate = 48000;
    int adev_in = AUDIO_DEVICE_CODEC;
    int adev_out = AUDIO_DEVICE_CODEC;
    int duration_s = 5;

    if (argc == 2 && !strcmp(argv[1], "-h"))
    {
        print_usage_adev(argv[0]);
        return 0;
    }
    else
    {
        for (i = 1; i < argc; )
        {
            if (!strcmp(argv[i], "-i"))
            {
                adev_in = atoi(argv[i + 1]);
                i += 2;
            }
            else if (!strcmp(argv[i], "-o"))
            {
                adev_out = atoi(argv[i + 1]);
                i += 2;
            }
            else if (!strcmp(argv[i], "-c"))
            {
                channels = atoi(argv[i + 1]);
                i += 2;
            }
            else if (!strcmp(argv[i], "-r"))
            {
                sample_rate = atoi(argv[i + 1]);
                i += 2;
            }
            else if (!strcmp(argv[i], "-t"))
            {
                duration_s = atoi(argv[i + 1]);
                i += 2;
            }
            else
            {
                i++;
            }
        }
    }

    /**
     * load audio path, once is OK after system boot.
     */
    lindmix_load_path(PCM_CAPTURE_MIC);
    lindmix_load_path(PCM_PLAYBACK_SPEAKER);

    context.h_ai = adev_in_create();
    if (context.h_ai == 0)
    {
        loge("adev_in_create failed");
        return -1;
    }

    context.ai_config.device = adev_in;
    context.ai_config.channels = channels;
    context.ai_config.rate = sample_rate;
    context.ai_config.bits = 16;
    context.ai_config.period_size = 1024;
    context.ai_config.period_count = 2;
    context.ai_config.pcm_cb = _ai_cb;
    context.ai_config.user = &context;

    ret = adev_in_open(context.h_ai, &context.ai_config);
    if (ret < 0)
    {
        loge("adev_in_open failed");
        return -1;
    }

    context.h_ao = adev_out_create();
    if (context.h_ao == 0)
    {
        loge("adev_out_create failed");
        return -1;
    }

    context.ao_config.device = adev_out;
    context.ao_config.channels = channels;
    context.ao_config.rate = sample_rate;
    context.ao_config.bits = 16;
    context.ao_config.period_size = 1024;
    context.ao_config.period_count = 2;
    context.ao_config.pcm_cb = NULL;
    context.ao_config.user = NULL;

    ret = adev_out_open(context.h_ao, &context.ao_config);
    if (ret < 0)
    {
        loge("adev_out_open failed");
        return -1;
    }

    sleep(duration_s);

    adev_in_destroy(context.h_ai);
    adev_out_destroy(context.h_ao);

    logd("bye bye");

    return 0;
}

